package com.xingzhi.shortvideosharingplatform.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xingzhi.shortvideosharingplatform.dto.CommentDTO;
import com.xingzhi.shortvideosharingplatform.dto.CommentTreeDTO;
import com.xingzhi.shortvideosharingplatform.mapper.CommentMapper;
import com.xingzhi.shortvideosharingplatform.mapper.CommentMentionMapper;
import com.xingzhi.shortvideosharingplatform.model.Comment;
import com.xingzhi.shortvideosharingplatform.model.CommentMention;
import com.xingzhi.shortvideosharingplatform.model.Users;
import com.xingzhi.shortvideosharingplatform.model.Video;
import com.xingzhi.shortvideosharingplatform.service.CommentService;
import com.xingzhi.shortvideosharingplatform.service.SystemNotificationService;
import com.xingzhi.shortvideosharingplatform.service.UserBehaviorLogsService;
import com.xingzhi.shortvideosharingplatform.service.VideoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    @Autowired
    private CommentMentionMapper commentMentionMapper;
    
    @Autowired
    private VideoService videoService;
    
    @Autowired
    private SystemNotificationService notificationService;
    
    @Autowired
    private UserBehaviorLogsService behaviorLogsService;

    @Override
    @Transactional
    public Long addComment(CommentDTO commentDTO) {
        try {
            // 1. 创建评论记录
            Comment comment = new Comment();
            comment.setUserId(commentDTO.getUserId());
            comment.setVideoId(commentDTO.getVideoId());
            comment.setContent(commentDTO.getContent());
            
            // parentId为可选参数，传递了则设置，否则不设置
            if (commentDTO.getParentId() > 0) {
                comment.setParentId(commentDTO.getParentId());
            }
            
            // replyToUserId为可选参数，传递了则设置，否则不设置
            if (commentDTO.getReplyToUserId() > 0) {
                comment.setReplyToUserId(commentDTO.getReplyToUserId());
            }
            
            comment.setLikeCount(0);
            comment.setIsDeleted(0);
            comment.setCreatedTime(LocalDateTime.now());
            comment.setUpdatedTime(comment.getCreatedTime());
            
            boolean saved = save(comment);
            if (!saved) {
                log.error("保存评论失败: {}", commentDTO);
                throw new RuntimeException("保存评论失败");
            }
            
            // 2. 获取视频所属用户ID
            Video video = videoService.getById(commentDTO.getVideoId());
            if (video == null) {
                throw new RuntimeException("视频不存在");
            }
            
            // 3. 增加视频评论数
            baseMapper.updateVideoCommentCount(commentDTO.getVideoId(), 1);
            
            // 4. 增加视频所属用户的评论数
            baseMapper.updateUserCommentCount(video.getUserId(), 1);
            
            // 5. 记录用户行为日志
            behaviorLogsService.recordCommentBehavior(
                commentDTO.getUserId(),
                commentDTO.getVideoId(),
                comment.getId()
            );
            
            // 6. 发送系统通知给视频所属者
            notificationService.sendCommentNotification(
                video.getUserId(),    // 接收通知的用户（视频所属者）
                commentDTO.getUserId(),// 评论者
                commentDTO.getVideoId(),
                comment.getId(),
                commentDTO.getContent()
            );
            
            // 7. 如果是回复评论，发送通知给被回复的用户
            if (commentDTO.getReplyToUserId() > 0) {
                notificationService.sendReplyNotification(
                    commentDTO.getReplyToUserId(),  // 接收通知的用户（被回复者）
                    commentDTO.getUserId(),         // 回复者
                    commentDTO.getVideoId(),
                    comment.getId(),
                    commentDTO.getContent()
                );
            }
            
            // 8. 处理@用户
            if (!CollectionUtils.isEmpty(commentDTO.getMentionedUserIds())) {
                LocalDateTime now = LocalDateTime.now();
                for (Long mentionedUserId : commentDTO.getMentionedUserIds()) {
                    // 创建评论提及记录
                    CommentMention mention = new CommentMention();
                    mention.setCommentId(comment.getId());
                    mention.setMentionedUserId(mentionedUserId);
                    mention.setVideoId(commentDTO.getVideoId());
                    mention.setReadStatus(0L); // 设置为未读状态
                    mention.setContent(commentDTO.getContent());
                    mention.setCreatedTime(now);
                    commentMentionMapper.insert(mention);
                    
                    // 发送@通知
                    notificationService.sendMentionNotification(
                        mentionedUserId,           // 接收通知的用户（被@的用户）
                        commentDTO.getUserId(),    // @的人
                        commentDTO.getVideoId(),
                        comment.getId(),
                        commentDTO.getContent()
                    );
                }
            }
            
            return comment.getId();
        } catch (Exception e) {
            log.error("创建评论失败", e);
            throw new RuntimeException("创建评论失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<CommentTreeDTO> getCommentTreeByVideoId(Long videoId) {
        // 1. 获取视频下所有未删除的评论
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Comment::getVideoId, videoId)
                   .eq(Comment::getIsDeleted, 0)
                   .orderByAsc(Comment::getId);
        
        List<Comment> allComments = baseMapper.selectList(queryWrapper);
        
        log.info("查询到的评论数量: {}", allComments.size());
        for (Comment comment : allComments) {
            log.info("评论详情: id={}, parentId={}, parentPath={}, content={}", 
                    comment.getId(), comment.getParentId(), comment.getParentPath(), comment.getContent());
        }
        
        if (CollectionUtils.isEmpty(allComments)) {
            return new ArrayList<>();
        }
        
        // 2. 获取评论中涉及的所有用户ID
        List<Long> userIds = allComments.stream()
                .map(Comment::getUserId)
                .distinct()
                .collect(Collectors.toList());
        
        // 3. 批量查询用户信息
        List<Users> users = baseMapper.selectUsersByIds(userIds);
        Map<Long, Users> userMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(users)) {
            userMap = users.stream().collect(Collectors.toMap(Users::getId, user -> user));
        }
        
        // 4. 将评论转为DTO并构建树形结构
        Map<Long, CommentTreeDTO> commentDTOMap = new HashMap<>();
        List<CommentTreeDTO> rootComments = new ArrayList<>();
        
        // 第一遍循环：创建所有的DTO对象
        for (Comment comment : allComments) {
            CommentTreeDTO commentDTO = convertToDTO(comment, userMap.get(comment.getUserId()));
            commentDTOMap.put(comment.getId(), commentDTO);
            log.info("创建DTO: id={}, userId={}, content={}", 
                    commentDTO.getId(), commentDTO.getUserId(), commentDTO.getContent());
        }
        
        // 第二遍循环：构建树形结构
        for (Comment comment : allComments) {
            CommentTreeDTO commentDTO = commentDTOMap.get(comment.getId());
            
            if (comment.getParentId() == null || comment.getParentId() == 0) {
                log.info("添加根评论: id={}", comment.getId());
                rootComments.add(commentDTO);
            } else {
                CommentTreeDTO parentDTO = commentDTOMap.get(comment.getParentId());
                if (parentDTO != null) {
                    log.info("添加子评论: id={}, parentId={}", comment.getId(), comment.getParentId());
                    parentDTO.getChildren().add(commentDTO);
                } else {
                    log.warn("未找到父评论，作为根评论处理: id={}, parentId={}", comment.getId(), comment.getParentId());
                    rootComments.add(commentDTO);
                }
            }
        }
        
        // 打印构建结果
        log.info("构建完成的根评论数量: {}", rootComments.size());
        for (CommentTreeDTO root : rootComments) {
            log.info("根评论: id={}, 子评论数量={}", root.getId(), root.getChildren().size());
            for (CommentTreeDTO child : root.getChildren()) {
                log.info("  - 子评论: id={}, parentId={}", child.getId(), root.getId());
            }
        }
        
        // 对根评论按创建时间倒序排序
        rootComments.sort((a, b) -> b.getCreatedTime().compareTo(a.getCreatedTime()));
        
        return rootComments;
    }
    
    @Override
    @Transactional
    public boolean incrementCommentLikeCount(Long commentId) {
        try {
            // 1. 检查评论是否存在
            Comment comment = getById(commentId);
            if (comment == null || comment.getIsDeleted() == 1) {
                log.error("评论不存在或已删除: {}", commentId);
                throw new RuntimeException("评论不存在或已删除");
            }
            
            // 2. 增加评论赞数
            int rows = baseMapper.incrementLikeCount(commentId);
            if (rows <= 0) {
                log.error("更新评论赞数失败: {}", commentId);
                return false;
            }
            
            return true;
        } catch (Exception e) {
            log.error("增加评论赞数失败", e);
            throw new RuntimeException("增加评论赞数失败: " + e.getMessage());
        }
    }
    
    @Override
    @Transactional
    public boolean decrementCommentLikeCount(Long commentId) {
        try {
            // 1. 检查评论是否存在
            Comment comment = getById(commentId);
            if (comment == null || comment.getIsDeleted() == 1) {
                log.error("评论不存在或已删除: {}", commentId);
                throw new RuntimeException("评论不存在或已删除");
            }
            
            // 2. 减少评论赞数
            int rows = baseMapper.decrementLikeCount(commentId);
            if (rows <= 0) {
                log.error("更新评论赞数失败: {}", commentId);
                return false;
            }
            
            return true;
        } catch (Exception e) {
            log.error("减少评论赞数失败", e);
            throw new RuntimeException("减少评论赞数失败: " + e.getMessage());
        }
    }
    
    private CommentTreeDTO convertToDTO(Comment comment, Users user) {
        CommentTreeDTO dto = new CommentTreeDTO();
        
        // 复制评论基本信息
        dto.setId(comment.getId());
        dto.setUserId(comment.getUserId());
        dto.setContent(comment.getContent());
        dto.setLikeCount(comment.getLikeCount());
        dto.setCreatedTime(comment.getCreatedTime());
        
        // 复制用户信息
        if (user != null) {
            dto.setUsername(user.getUsername());
            dto.setNickname(user.getNickname());
            dto.setAvatar(user.getAvatar());
            dto.setRegion(user.getRegion());
        }
        
        return dto;
    }
} 
